﻿using System;
using System.Configuration;
using SeleniumToolkit.Util;

namespace SeleniumToolkit.Config
{
    /// <summary>
    /// Configuration element that defines how the selenium-rc process is controlled
    /// </summary>
    public class SeleniumConfigurationRuntimeElement : ConfigurationElement
    {
        static SeleniumConfigurationRuntimeElement()
        {
            PropertyCollection = new ConfigurationPropertyCollection();

            AutoStartProperty = new ConfigurationProperty(AutoStartKey, typeof(bool), AutoStartDefault);
            AutoStopProperty = new ConfigurationProperty(AutoStopKey, typeof(bool), AutoStopDefault);
            SeleniumRcPathProperty = new ConfigurationProperty(SeleniumRuntimePathKey, typeof(string), null, ConfigurationPropertyOptions.IsRequired);
            HideProcessProperty = new ConfigurationProperty(HideProcessKey, typeof(bool), HideProcessDefault, ConfigurationPropertyOptions.None);
            
            // process username and password
            UserNameProperty = new ConfigurationProperty(UserNameKey, typeof(string), null, ConfigurationPropertyOptions.None);
            PasswordProperty = new ConfigurationProperty(PasswordKey, typeof(string), null, ConfigurationPropertyOptions.None);

            // proxy server settings
            ProxyServerProperty = new ConfigurationProperty(ProxyServerKey, typeof(string), null, ConfigurationPropertyOptions.None);
            ProxyPortProperty = new ConfigurationProperty(ProxyPortKey, typeof(int), ProxyPortDefault, ConfigurationPropertyOptions.None);
            ProxyUserProperty = new ConfigurationProperty(ProxyUserKey, typeof(string), null, ConfigurationPropertyOptions.None);
            ProxyPasswordProperty = new ConfigurationProperty(ProxyPasswordKey, typeof(string), null, ConfigurationPropertyOptions.None);

            PropertyCollection.Add(AutoStartProperty);
            PropertyCollection.Add(AutoStopProperty);
            PropertyCollection.Add(SeleniumRcPathProperty);
            PropertyCollection.Add(HideProcessProperty);
            PropertyCollection.Add(UserNameProperty);
            PropertyCollection.Add(PasswordProperty);
            PropertyCollection.Add(ProxyServerProperty);
            PropertyCollection.Add(ProxyPortProperty);
            PropertyCollection.Add(ProxyUserProperty);
            PropertyCollection.Add(ProxyPasswordProperty);
        }

        /// <summary>
        /// Gets the collection of Configuration Properties
        /// </summary>
        protected override ConfigurationPropertyCollection Properties
        {
            get
            {
                return PropertyCollection;
            }
        }

        #region Configuration Attributes
        /// <summary>
        /// Determines whether a local instance of selenium-rc should be started at the beginning of a test run
        /// </summary>
        [ConfigurationProperty(AutoStartKey, DefaultValue = AutoStartDefault)]
        public bool AutoStart
        {
            get { return (bool)base[AutoStartProperty]; }
            set { base[AutoStartProperty] = value; }
        }

        /// <summary>
        /// Determines whether a local instance of selenium-rc should be stopped at the end of a test run
        /// </summary>
        [ConfigurationProperty(AutoStopKey, DefaultValue = AutoStopDefault)]
        public bool AutoStop
        {
            get { return (bool)base[AutoStopProperty]; }
            set { base[AutoStopProperty] = value; }
        }

        /// <summary>
        /// File path pointing to the folder containing the selenium remote control binaries
        /// </summary>
        [ConfigurationProperty(SeleniumRuntimePathKey)]
        public string SeleniumRuntimePath
        {
            get 
            {
                var runtimePath = base[SeleniumRcPathProperty] as string;
                if (!String.IsNullOrEmpty(runtimePath))
                    return runtimePath;
                
                var helper = new RegistryKeyHelper(@"SOFTWARE\SeleniumToolkit");
                if (helper.RegistryKeyExists)
                {
                    string installDir = helper.GetValue("InstallDir");
                    if (!String.IsNullOrEmpty(installDir))
                    {
                        return System.IO.Path.Combine(installDir, @"bin\selenium-rc");
                    }
                }
                string message = String.Format("Missing \"{0}\" attribute from Selenium\\runtime element", SeleniumRuntimePathKey);
                throw new ConfigurationErrorsException(message);
            }
            set { base[SeleniumRcPathProperty] = value; }
        }

        /// <summary>
        /// Hides the Selenium RC Process while executing
        /// </summary>
        [ConfigurationProperty(HideProcessKey, DefaultValue = HideProcessDefault)]
        public bool HideRuntimeProcess
        {
            get { return Convert.ToBoolean(base[HideProcessProperty]); }
            set { base[HideProcessProperty] = value; }
        }

        /// <summary>
        /// Username for Process
        /// </summary>
        [ConfigurationProperty(UserNameKey)]
        public string UserName
        {
            get { return (string)base[UserNameProperty]; }
            set { base[UserNameProperty] = value; }
        }

        /// <summary>
        /// Password for Process
        /// </summary>
        [ConfigurationProperty(PasswordKey)]
        public string Password
        {
            get { return (string)base[PasswordProperty]; }
            set { base[PasswordProperty] = value; }
        }

        /// <summary>
        /// Proxy Server Server Name
        /// </summary>
        [ConfigurationProperty(ProxyServerKey)]
        public string ProxyServer
        {
            get { return (string)base[ProxyServerProperty]; }
            set { base[ProxyServerProperty] = value; }
        }

        /// <summary>
        /// Proxy Server Port Number
        /// </summary>
        [ConfigurationProperty(ProxyPortKey)]
        public int ProxyPort
        {
            get { return (int)base[ProxyPortProperty]; }
            set { base[ProxyPortProperty] = value; }
        }

        /// <summary>
        /// Proxy Server User Name
        /// </summary>
        [ConfigurationProperty(ProxyUserKey)]
        public string ProxyUser
        {
            get { return (string)base[ProxyUserProperty]; }
            set { base[ProxyUserProperty] = value; }
        }

        /// <summary>
        /// Proxy Server Password
        /// </summary>
        [ConfigurationProperty(ProxyPasswordKey)]
        public string ProxyPassword
        {
            get { return (string)base[ProxyPasswordProperty]; }
            set { base[ProxyPasswordProperty] = value; }
        }

        private static readonly ConfigurationProperty AutoStartProperty;
        private const string AutoStartKey = "autoStart";
        private const bool AutoStartDefault = true;

        private static readonly ConfigurationProperty AutoStopProperty;
        private const string AutoStopKey = "autoStop";
        private const bool AutoStopDefault = true;

        private static readonly ConfigurationProperty SeleniumRcPathProperty;
        private const string SeleniumRuntimePathKey = "location";

        private static readonly ConfigurationProperty HideProcessProperty;
        private const string HideProcessKey = "hidden";
        private const bool HideProcessDefault = true;

        private static readonly ConfigurationProperty UserNameProperty;
        private const string UserNameKey = "username";

        private static readonly ConfigurationProperty PasswordProperty;
        private const string PasswordKey = "password";

        private static readonly ConfigurationProperty ProxyServerProperty;
        private const string ProxyServerKey = "proxyServer";

        private static readonly ConfigurationProperty ProxyPortProperty;
        private const string ProxyPortKey = "proxyPort";
        private const int ProxyPortDefault = 8080;

        private static readonly ConfigurationProperty ProxyUserProperty;
        private const string ProxyUserKey = "proxyUser";

        private static readonly ConfigurationProperty ProxyPasswordProperty;
        private const string ProxyPasswordKey = "proxyPassword";

        
        #endregion

        private static readonly ConfigurationPropertyCollection PropertyCollection;
    }
}
